package org.dromara.common.social.utils

import me.zhyd.oauth.config.AuthConfig
import me.zhyd.oauth.exception.AuthException
import me.zhyd.oauth.model.AuthCallback
import me.zhyd.oauth.model.AuthResponse
import me.zhyd.oauth.model.AuthUser
import me.zhyd.oauth.request.*
import org.dromara.common.core.utils.SpringUtils.getBean
import org.dromara.common.social.config.properties.SocialProperties
import org.dromara.common.social.gitea.AuthGiteaRequest
import org.dromara.common.social.maxkey.AuthMaxKeyRequest
import org.dromara.common.social.topiam.AuthTopIamRequest
import java.net.URLEncoder
import java.nio.charset.StandardCharsets

/**
 * 认证授权工具类
 *
 * @author thiszhc
 * @updater LikeYouDo
 * @date 2025/1/7 09:53
 */
object SocialUtils {
    private val STATE_CACHE: AuthRedisStateCache = getBean(AuthRedisStateCache::class.java)

    @JvmStatic
    @Throws(AuthException::class)
    @Suppress("UNCHECKED_CAST")
    fun loginAuth(
        source: String,
        code: String,
        state: String,
        socialProperties: SocialProperties
    ): AuthResponse<AuthUser> {
        val authRequest = getAuthRequest(source, socialProperties)
        val callback = AuthCallback()
        callback.code = code
        callback.state = state
        return authRequest.login(callback) as AuthResponse<AuthUser>
    }

    @JvmStatic
    @Throws(AuthException::class)
    fun getAuthRequest(source: String, socialProperties: SocialProperties): AuthRequest {
        val obj = socialProperties.type[source] ?: throw AuthException("不支持的第三方登录类型")
        val builder = AuthConfig.builder()
            .clientId(obj.clientId)
            .clientSecret(obj.clientSecret)
            .redirectUri(URLEncoder.encode(obj.redirectUri, StandardCharsets.UTF_8))
            .scopes(obj.scopes)
        return when (source.lowercase()) {
            "dingtalk" -> AuthDingTalkV2Request(builder.build(), STATE_CACHE)
            "baidu" -> AuthBaiduRequest(builder.build(), STATE_CACHE)
            "github" -> AuthGithubRequest(builder.build(), STATE_CACHE)
            "gitee" -> AuthGiteeRequest(builder.build(), STATE_CACHE)
            "weibo" -> AuthWeiboRequest(builder.build(), STATE_CACHE)
            "coding" -> AuthCodingRequest(builder.build(), STATE_CACHE)
            "oschina" -> AuthOschinaRequest(builder.build(), STATE_CACHE)
            // 支付宝在创建回调地址时，不允许使用localhost或者127.0.0.1，所以这儿的回调地址使用的局域网内的ip
            "alipay_wallet" -> AuthAlipayRequest(
                builder.build(),
                socialProperties.type["alipay_wallet"]!!.alipayPublicKey,
                STATE_CACHE
            )

            "qq" -> AuthQqRequest(builder.build(), STATE_CACHE)
            "wechat_open" -> AuthWeChatOpenRequest(builder.build(), STATE_CACHE)
            "taobao" -> AuthTaobaoRequest(builder.build(), STATE_CACHE)
            "douyin" -> AuthDouyinRequest(builder.build(), STATE_CACHE)
            "linkedin" -> AuthLinkedinRequest(builder.build(), STATE_CACHE)
            "microsoft" -> AuthMicrosoftRequest(builder.build(), STATE_CACHE)
            "renren" -> AuthRenrenRequest(builder.build(), STATE_CACHE)
            "stack_overflow" -> AuthStackOverflowRequest(builder.stackOverflowKey(obj.stackOverflowKey).build(), STATE_CACHE)
            "huawei" -> AuthHuaweiV3Request(builder.build(), STATE_CACHE)
            "wechat_enterprise" -> AuthWeChatEnterpriseQrcodeV2Request(builder.agentId(obj.agentId).build(), STATE_CACHE)
            "gitlab" -> AuthGitlabRequest(builder.build(), STATE_CACHE)
            "wechat_mp" -> AuthWeChatMpRequest(builder.build(), STATE_CACHE)
            "aliyun" -> AuthAliyunRequest(builder.build(), STATE_CACHE)
            "maxkey" -> AuthMaxKeyRequest(builder.build(), STATE_CACHE)
            "topiam" -> AuthTopIamRequest(builder.build(), STATE_CACHE)
            "gitea" -> AuthGiteaRequest(builder.build(), STATE_CACHE)
            else -> throw AuthException("未获取到有效的Auth配置")
        }
    }
}
